package com.example.androidautoproject.utils

import android.graphics.Rect
import android.text.TextUtils
import android.util.Log
import android.view.accessibility.AccessibilityNodeInfo
import com.ven.assists.AssistsCore
import com.ven.assists.AssistsCore.findFirstParentClickable
import com.ven.assists.AssistsCore.isImageButton
import com.ven.assists.AssistsCore.isImageView
import com.ven.assists.AssistsCore.isTextView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.ArrayList
import kotlin.random.Random

object AutoScript {
    var ran_time = Random.nextLong(0L, 1000L)
    var ran = Random.nextDouble(-5.0, 5.0)
    suspend fun close_app(){
        AssistsCore.home()
        Thread.sleep(5000)
        AssistsCore.recentApps()
        Thread.sleep(3000)
        AssistsCore.gesture(
            floatArrayOf((531f + ran).toFloat(), (1533f + ran).toFloat()),
            floatArrayOf((564f + ran).toFloat(), (238f + ran).toFloat()),
            500L,
            1000L)

    }

    suspend fun vertical_swipe(){
        AssistsCore.gesture(
            floatArrayOf((525f + ran).toFloat(), (1929f + ran).toFloat()),
            floatArrayOf((567f + ran).toFloat(), (430f + ran).toFloat()),
            500L,
            1000L)
    }

    suspend fun vertical_swipe_up(){
        AssistsCore.gesture(
            floatArrayOf((567f + ran).toFloat(), (430f + ran).toFloat()),
            floatArrayOf((525f + ran).toFloat(), (1929f + ran).toFloat()),
            500L,
            1000L)
    }

    suspend fun horizontal_swipe(){
        AssistsCore.gesture(
            floatArrayOf((984f + ran).toFloat(), (345f + ran).toFloat()),
            floatArrayOf((144f + ran).toFloat(), (346f + ran).toFloat()),
            500L,
            1000L)
    }

    fun ran_sleep(baseTime: Long, onDelayComplete:() ->Unit){
        CoroutineScope(Dispatchers.Default).launch {
            val delayTime = maxOf(0, baseTime + ran_time)
            delay(delayTime)
            launch(Dispatchers.Main){
                onDelayComplete()
            }
        }
    }

    suspend fun ran_click(x:Float, y:Float){
        LogWrapper.logAppend("ran_click ${x + ran} x ${y + ran} ")
        AssistsCore.gestureClick((x + ran).toFloat(), (y + ran).toFloat())
    }

    suspend fun click_element(nodeInfo: AccessibilityNodeInfo){
        val bounds = Rect()
        nodeInfo.getBoundsInScreen(bounds)
        val randomX = bounds.left + Random.nextInt(bounds.width())
        val randomY = bounds.top + Random.nextInt(bounds.height())
        Log.e(AdParam.currentTag, "${nodeInfo.text} x ${randomX} y ${randomY}")
        LogWrapper.logAppend("${nodeInfo.text} x ${randomX} y ${randomY}")
        AssistsCore.gestureClick(randomX.toFloat(), randomY.toFloat())
    }

    suspend fun click_elementById(id: String){
        var node = AssistsCore.findById(id).firstOrNull()?.findFirstParentClickable()
        if(node != null) {
            click_element(node)
        }
    }

    suspend fun click_element_by_text(text:String):Boolean{
        var nodes = AssistsCore.getAllNodes()
        var bool = false
        nodes.forEach{it
            val bounds = Rect()
            it.getBoundsInScreen(bounds)
            // Log.e("UcProject", "${it.text} ${it.isVisibleToUser} ${it.isTextView()} ${!TextUtils.isEmpty(it.text)} ")
//                    && it.isTextView() it.isVisibleToUser &&
            if(
                !TextUtils.isEmpty(it.text) &&
                it.text.indexOf(text) >= 0
            ){
                bool = true
                click_element(it)
                Thread.sleep(1000)
            }
            it.recycle()
        }
        if (bool) {
            return true
        } else {
            return false
        }
    }

    suspend fun click_element_by_textAndPosition(text:String, x:Int, y:Int):Boolean{
        var nodes = AssistsCore.getAllNodes()
        var bool = false
        nodes.forEach{it
            val bounds = Rect()
            it.getBoundsInScreen(bounds)
//                    && it.isTextView()
            if(
                it.isVisibleToUser &&
                !TextUtils.isEmpty(it.text) &&
                it.text.indexOf(text) >= 0 &&
                bounds.bottom < y &&
                bounds.right < x
            ){
                bool = true
                click_element(it)
                Thread.sleep(1000)
            }
            it.recycle()
        }
        if (bool) {
            return true
        } else {
            return false
        }
    }

    suspend fun click_element_by_textAndIndex(text: String, index:Int):Boolean{
        var bool = false
        var nodes = AssistsCore.getAllNodes()
        var i = 0
        nodes.forEach{it
            if(it.isVisibleToUser &&  !TextUtils.isEmpty(it.text) && it.text.indexOf(text) >= 0){
                bool = true
                if(i === index) {
                    click_element(it)
                }
                Thread.sleep(1000)
                i++
            }
            it.recycle()
        }
        if (bool) {
            return true
        } else {
            return false
        }
    }

    suspend fun find_element_by_text(text:String):Boolean{
        var nodes = AssistsCore.getAllNodes()
        var bool = false
//        it.isTextView() &&
        nodes.forEach{it
            if(it.isVisibleToUser &&  !TextUtils.isEmpty(it.text) && it.text.indexOf(text) >= 0){
                bool = true
            }
            it.recycle()
        }
        if (bool) {
            return true

        } else {
            return false
        }
    }

    suspend fun closeWinBySize(width:Int, height:Int):Boolean{
        var nodes = AssistsCore.getAllNodes()
        var bool = false
        nodes.forEach{it
            val bounds = Rect()
            it.getBoundsInScreen(bounds)
//            it.isVisibleToUser &&
            if (
                (it.isImageView() || it.isImageButton() || it.className?.toString()!!.contains("image", ignoreCase = true)) &&
                (bounds.right - bounds.left == width && bounds.bottom - bounds.top == height)
           ){
                bool = true
                click_element(it)
            }
            it.recycle()
        }
        if (bool) {
            return true
        } else {
            return false
        }
    }

    suspend fun closeWinBySizeOnly(width:Int, height:Int):Boolean{
        var nodes = AssistsCore.getAllNodes()
        var bool = false
        nodes.forEach{it
            val bounds = Rect()
            it.getBoundsInScreen(bounds)
            //                it.isClickable &&
            if (
                it.isVisibleToUser &&
                (bounds.right - bounds.left == width && bounds.bottom - bounds.top == height) &&
                bounds.bottom < 400
            ){
                bool = true
                click_element(it)
            }
            it.recycle()
        }
        if (bool) {
            return true
        } else {
            return false
        }
    }
    suspend fun closeWinBySizeOnlyNotVisible(width:Int, height:Int):Boolean{
        var nodes = AssistsCore.getAllNodes()
        var bool = false
        nodes.forEach{it
            val bounds = Rect()
            it.getBoundsInScreen(bounds)
            if (
                (bounds.right - bounds.left == width && bounds.bottom - bounds.top == height) &&
                bounds.bottom < 600
            ){
                bool = true
                click_element(it)
            }
            it.recycle()
        }
        if (bool) {
            return true
        } else {
            return false
        }
    }

    fun getChildNodesById(id: String):MutableList<AccessibilityNodeInfo>{
        var nodes = AssistsCore.findById(id)
        var arrList:MutableList<AccessibilityNodeInfo> = mutableListOf()
        nodes[0]?.let { node ->
            convertNode(node, arrList)
            node.recycle()
        }
        return arrList
    }

    fun convertNode(node: AccessibilityNodeInfo, arrList:MutableList<AccessibilityNodeInfo>){
        for(i in 0 until node.childCount){
            node.getChild(i)?.let { child ->
                arrList.add(child)
                convertNode(child, arrList)
                child.recycle()
            }
        }
    }
}